package com.jingdianjichi.auth.application.interceptor;

import com.jingdianjichi.auth.application.context.LoginContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Slf4j
@Component
public class LoginInterceptor implements HandlerInterceptor {

    /**
     * 用户ID请求头名称
     * 与网关中LoginIdTransferFilter设置的请求头名称保持一致
     */
    private static final String LOGIN_ID_HEADER = "loginId";

    /**
     * 请求处理前的拦截方法
     *
     * 从请求头中提取loginId并存储到ThreadLocal中。
     * 这个方法在Controller方法执行前调用。
     *
     * @param request HTTP请求对象
     * @param response HTTP响应对象
     * @param handler 处理器对象
     * @return true-继续处理请求，false-中断请求处理
     * @throws Exception 处理异常
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        log.info("准备拦截请求，URI: {}", request.getRequestURI());

        // 从请求头中获取loginId
        String loginId = request.getHeader(LOGIN_ID_HEADER);

        log.info("请求头中获取到的loginId: {}, URI: {}", loginId, request.getRequestURI());

        if (StringUtils.hasText(loginId)) {
            // 将用户信息存储到ThreadLocal中
            LoginContextHolder.set(loginId);
            log.debug("设置当前线程用户信息，loginId: {}, URI: {}", loginId, request.getRequestURI());
        } else {
            log.debug("请求头中未找到loginId信息，URI: {}", request.getRequestURI());
        }

        // 继续处理请求
        return true;
    }

    /**
     * 请求处理完成后的清理方法
     *
     * 清除ThreadLocal中的用户信息，防止内存泄漏。
     * 这个方法在整个请求处理完成后调用，包括视图渲染完成后。
     *
     * 重要：无论请求处理成功还是失败，都会调用这个方法，
     * 确保ThreadLocal一定会被清理。
     *
     * @param request HTTP请求对象
     * @param response HTTP响应对象
     * @param handler 处理器对象
     * @param ex 如果处理过程中发生异常，这里会传入异常对象
     * @throws Exception 处理异常
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
        try {
            // 获取当前用户信息用于日志记录
            String loginId = LoginContextHolder.getLoginId();
            if (loginId != null) {
                log.debug("清除当前线程用户信息，loginId: {}, URI: {}", loginId, request.getRequestURI());
            }
        } finally {
            // 无论如何都要清除ThreadLocal，防止内存泄漏
            LoginContextHolder.clear();
        }
    }
}
